package com.estore.service;

import com.estore.model.Product;
import java.io.*;
import java.util.*;

/**
 * 商品服务类，负责商品相关的业务逻辑
 * 使用内存Map模拟数据库存储，支持数据持久化、配置文件管理和数据备份
 */
public class ProductService {

    // 使用Map存储商品数据，key是商品ID，value是商品对象
    private final Map<String, Product> productData = new HashMap<>();

    // 配置文件路径
    private static final String CONFIG_FILE = "config.properties";
    // 数据文件路径（从配置文件读取）
    private String dataFilePath;

    /**
     * 构造函数，初始化商品数据
     */
    public ProductService() {
        // 首先加载配置文件
        if (loadConfig()) {
            System.out.println("配置文件加载成功，数据文件路径: " + dataFilePath);
        } else {
            // 如果配置文件加载失败，使用默认路径
            dataFilePath = "products.dat";
            System.out.println("使用默认数据文件路径: " + dataFilePath);
        }

        // 然后尝试从文件加载数据
        if (!loadData()) {
            // 如果加载失败，初始化示例数据
            System.out.println("未找到保存的数据文件，初始化示例数据...");
            initializeSampleData();
        } else {
            System.out.println("成功加载保存的商品数据！");
        }
    }

    /**
     * 备份数据文件
     * @return 是否备份成功
     */
    public boolean backupData() {
        // 确保数据文件路径不为空
        if (dataFilePath == null || dataFilePath.trim().isEmpty()) {
            dataFilePath = "products.dat";
        }

        File sourceFile = new File(dataFilePath);
        if (!sourceFile.exists()) {
            System.out.println("源数据文件 " + dataFilePath + " 不存在，无法备份");
            return false;
        }

        String backupFilePath = dataFilePath + ".bak";
        File backupFile = new File(backupFilePath);

        // 使用最基础的 FileInputStream 和 FileOutputStream 进行备份
        try (FileInputStream fis = new FileInputStream(sourceFile);
             FileOutputStream fos = new FileOutputStream(backupFile)) {

            // 创建字节数组作为缓冲区
            byte[] buffer = new byte[1024];
            int bytesRead;
            long totalBytes = 0;

            System.out.println("开始备份数据文件...");
            System.out.println("源文件: " + dataFilePath);
            System.out.println("目标文件: " + backupFilePath);

            // 通过循环读取和写入数据
            while ((bytesRead = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
                totalBytes += bytesRead;
            }

            System.out.println("备份完成！总共备份了 " + totalBytes + " 字节");
            System.out.println("备份文件大小: " + backupFile.length() + " 字节");

            // 验证备份文件是否创建成功
            if (backupFile.exists() && backupFile.length() > 0) {
                System.out.println("✅ 数据备份成功！");
                return true;
            } else {
                System.out.println("❌ 备份文件创建失败");
                return false;
            }

        } catch (FileNotFoundException e) {
            System.err.println("文件未找到: " + e.getMessage());
            return false;
        } catch (IOException e) {
            System.err.println("备份过程中发生IO错误: " + e.getMessage());
            return false;
        }
    }

    /**
     * 从备份文件恢复数据
     * @return 是否恢复成功
     */
    public boolean restoreFromBackup() {
        String backupFilePath = dataFilePath + ".bak";
        File backupFile = new File(backupFilePath);

        if (!backupFile.exists()) {
            System.out.println("备份文件 " + backupFilePath + " 不存在，无法恢复");
            return false;
        }

        File dataFile = new File(dataFilePath);

        // 使用最基础的 FileInputStream 和 FileOutputStream 进行恢复
        try (FileInputStream fis = new FileInputStream(backupFile);
             FileOutputStream fos = new FileOutputStream(dataFile)) {

            // 创建字节数组作为缓冲区
            byte[] buffer = new byte[1024];
            int bytesRead;
            long totalBytes = 0;

            System.out.println("开始从备份恢复数据...");
            System.out.println("源文件: " + backupFilePath);
            System.out.println("目标文件: " + dataFilePath);

            // 通过循环读取和写入数据
            while ((bytesRead = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
                totalBytes += bytesRead;
            }

            System.out.println("恢复完成！总共恢复了 " + totalBytes + " 字节");

            // 重新加载数据到内存
            if (loadData()) {
                System.out.println("✅ 数据恢复成功！");
                return true;
            } else {
                System.out.println("❌ 数据恢复后加载失败");
                return false;
            }

        } catch (FileNotFoundException e) {
            System.err.println("文件未找到: " + e.getMessage());
            return false;
        } catch (IOException e) {
            System.err.println("恢复过程中发生IO错误: " + e.getMessage());
            return false;
        }
    }

    /**
     * 检查备份文件是否存在
     * @return 备份文件是否存在
     */
    public boolean backupExists() {
        String backupFilePath = dataFilePath + ".bak";
        File backupFile = new File(backupFilePath);
        return backupFile.exists() && backupFile.length() > 0;
    }

    /**
     * 获取备份文件信息
     * @return 备份文件信息字符串
     */
    public String getBackupInfo() {
        String backupFilePath = dataFilePath + ".bak";
        File backupFile = new File(backupFilePath);

        if (backupFile.exists()) {
            return String.format("备份文件: %s (大小: %d 字节, 最后修改: %s)",
                    backupFilePath,
                    backupFile.length(),
                    new Date(backupFile.lastModified()));
        } else {
            return "暂无备份文件";
        }
    }

    /**
     * 加载配置文件
     * @return 是否加载成功
     */
    private boolean loadConfig() {
        File configFile = new File(CONFIG_FILE);
        if (!configFile.exists()) {
            System.out.println("配置文件 " + CONFIG_FILE + " 不存在，将使用默认配置");
            return false;
        }

        Properties props = new Properties();
        // 使用字符流和转换流读取配置文件，支持UTF-8编码
        try (InputStreamReader reader = new InputStreamReader(
                new FileInputStream(CONFIG_FILE), "UTF-8")) {

            props.load(reader);

            // 读取数据文件路径配置
            dataFilePath = props.getProperty("data.file.path");
            if (dataFilePath == null || dataFilePath.trim().isEmpty()) {
                System.err.println("配置文件中未找到 data.file.path 配置项");
                return false;
            }

            System.out.println("从配置文件读取到数据文件路径: " + dataFilePath);
            return true;

        } catch (UnsupportedEncodingException e) {
            System.err.println("不支持的编码格式: " + e.getMessage());
            return false;
        } catch (IOException e) {
            System.err.println("读取配置文件失败: " + e.getMessage());
            return false;
        }
    }

    /**
     * 保存数据到文件
     * @return 是否保存成功
     */
    public boolean saveData() {
        // 确保数据文件路径不为空
        if (dataFilePath == null || dataFilePath.trim().isEmpty()) {
            dataFilePath = "products.dat";
            System.out.println("数据文件路径为空，使用默认路径: " + dataFilePath);
        }

        try (ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(dataFilePath))) {

            oos.writeObject(productData);
            System.out.println("商品数据已成功保存到文件: " + dataFilePath);
            return true;

        } catch (IOException e) {
            System.err.println("保存商品数据到 " + dataFilePath + " 失败: " + e.getMessage());
            return false;
        }
    }

    /**
     * 从文件加载数据
     * @return 是否加载成功
     */
    @SuppressWarnings("unchecked")
    private boolean loadData() {
        // 确保数据文件路径不为空
        if (dataFilePath == null || dataFilePath.trim().isEmpty()) {
            dataFilePath = "products.dat";
            System.out.println("数据文件路径为空，使用默认路径: " + dataFilePath);
        }

        File dataFile = new File(dataFilePath);
        if (!dataFile.exists()) {
            System.out.println("数据文件 " + dataFilePath + " 不存在，将使用示例数据");
            return false;
        }

        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(dataFilePath))) {

            Object obj = ois.readObject();
            if (obj instanceof Map) {
                Map<String, Product> loadedData = (Map<String, Product>) obj;
                productData.clear();
                productData.putAll(loadedData);
                System.out.println("成功从 " + dataFilePath + " 加载 " + productData.size() + " 个商品数据");
                return true;
            } else {
                System.err.println("数据文件格式不正确");
                return false;
            }

        } catch (IOException | ClassNotFoundException e) {
            System.err.println("从 " + dataFilePath + " 加载商品数据失败: " + e.getMessage());
            return false;
        }
    }

    /**
     * 获取当前使用的数据文件路径
     * @return 数据文件路径
     */
    public String getDataFilePath() {
        return dataFilePath != null ? dataFilePath : "products.dat";
    }

    /**
     * 重新加载配置（可用于运行时更新配置）
     * @return 是否重新加载成功
     */
    public boolean reloadConfig() {
        System.out.println("重新加载配置文件...");
        return loadConfig();
    }

    /**
     * 初始化示例数据（仅在首次运行时使用）
     */
    private void initializeSampleData() {
        // 为Java图书创建标签
        Set<String> tagsForJavaBook = new HashSet<>();
        tagsForJavaBook.add("编程");
        tagsForJavaBook.add("畅销");
        tagsForJavaBook.add("热门");

        productData.put("p001", new Product("p001", "Java从入门到精通", 99.0, 100, tagsForJavaBook));

        // 为MySQL图书创建标签
        Set<String> tagsForMysqlBook = new HashSet<>();
        tagsForMysqlBook.add("数据库");
        tagsForMysqlBook.add("技术");
        tagsForMysqlBook.add("热门");

        productData.put("p002", new Product("p002", "高性能MySQL", 128.5, 50, tagsForMysqlBook));

        // 为健康类商品创建标签
        Set<String> tagsForHealth = new HashSet<>();
        tagsForHealth.add("健康");
        tagsForHealth.add("生活");
        tagsForHealth.add("保健");

        productData.put("p003", new Product("p003", "颈椎康复指南", 45.0, 200, tagsForHealth));

        // 为美容类商品创建标签
        Set<String> tagsForBeauty = new HashSet<>();
        tagsForBeauty.add("美容");
        tagsForBeauty.add("生活");
        tagsForBeauty.add("新品");

        productData.put("p004", new Product("p004", "生发秘籍", 88.0, 0, tagsForBeauty));

        // 家电商品（不带标签）
        productData.put("p005", new Product("p005", "小猫净化器", 188.0, 40));

        // 日用品（不带标签）
        productData.put("p006", new Product("p006", "水杯", 28.0, 10));

        System.out.println("示例数据初始化完成，共 " + productData.size() + " 个商品");
    }

    // 原有的业务方法保持不变...
    /**
     * 获取所有商品列表
     * @return 商品列表
     */
    public List<Product> getAllProducts() {
        return new ArrayList<>(productData.values());
    }

    /**
     *
     *
     *
     *
     *
     * 根据ID查找商品
     * @param id 商品ID
     * @return 找到的商品对象，如果不存在则返回null
     */
    public Product findProductById(String id) {
        return productData.get(id);
    }

    /**
     * 添加新商品
     * @param product 商品对象
     * @return 是否添加成功
     */
    public boolean addProduct(Product product) {
        if (product == null || productData.containsKey(product.getId())) {
            return false;
        }
        productData.put(product.getId(), product);
        return true;
    }

    /**
     * 更新商品信息
     * @param product 商品对象
     * @return 是否更新成功
     */
    public boolean updateProduct(Product product) {
        if (product == null || !productData.containsKey(product.getId())) {
            return false;
        }
        productData.put(product.getId(), product);
        return true;
    }

    /**
     * 删除商品
     * @param id 商品ID
     * @return 是否删除成功
     */
    public boolean deleteProduct(String id) {
        return productData.remove(id) != null;
    }

    /**
     * 减少商品库存
     * @param id 商品ID
     * @param quantity 减少数量
     * @return 是否成功
     */
    public boolean decreaseStock(String id, int quantity) {
        Product product = findProductById(id);
        if (product == null) {
            return false;
        }
        return product.decreaseStock(quantity);
    }

    /**
     * 获取商品总数
     * @return 商品数量
     */
    public int getProductCount() {
        return productData.size();
    }

    /**
     * 打印所有商品信息
     */
    public void printAllProducts() {
        System.out.println("=== 所有商品信息 ===");
        for (Product product : getAllProducts()) {
            System.out.println(product);
        }
        System.out.println("===================");
    }
}